﻿using System;
using System.Collections.Generic;
using System.Windows.Media;

namespace Rage.HealMerc
{
    [Rage.Calculations.RageModelInfo("HealMerc", "Spell_Holy_Renew", CharacterClass.Mercenary)]
    public class CalculationsHealMerc : CalculationsBase
    {
        #region Variables and Properties
        #endregion

        #region Gemming Templates
        public override List<GemmingTemplate> DefaultGemmingTemplates
        {
            get
            {
                // Relevant Mod IDs for Class

                //              "22/50-Green", "22/50-Blue", "22/50-Purple", "23/51-Tionese", "24/56-Columi", "25/58-Rakata"
                string[] armr = { "", "", "", "", "", "", };
                string[] barl = { "", "", "", "", "", "", };
                string[] hilt = { "", "", "", "", "", "", };
                string[] mods = { "", "", "", "", "", "", };
                string[] enhm = { "", "", "", "", "", "", };
                string[] clcr = { "", "", "", "", "", "", };
                string[] augm = { "", "", "", "", "", "", };

                List<GemmingTemplate> list = new List<GemmingTemplate>();
                for (int tier = 0; tier < 6; tier++)
                {
                    list.AddRange(new GemmingTemplate[]
                        {
                            CreateGemmingTemplate(tier, armr, barl, hilt, mods, enhm, clcr, augm),
                            //CreateGemmingTemplate(tier, armr, armr, glinting, delicate, keen, keen, keen),
                            //CreateGemmingTemplate(tier, armr, armr, glinting, delicate, keen, keen, keen),
                        });
                }
                return list;
            }
        }

        private const int DEFAULT_GEMMING_TIER = 3;
        private GemmingTemplate CreateGemmingTemplate(int tier,
            string[] armoring, string[] barrel, string[] hilt,
            string[] mod, string[] enhancement, string[] colorcrystal, string[] augment)
        {
            return new GemmingTemplate()
            {
                Model = "Assassin",
                Group = (new string[] { "22/50-Green", "22/50-Blue", "22/50-Purple", "23/51-Tionese", "24/56-Columi", "25/58-Rakata" })[tier],
                Enabled = (tier == DEFAULT_GEMMING_TIER),

                ArmoringId = armoring[tier],
                BarrelId = barrel[tier],
                HiltId = hilt[tier],
                ModId = mod[tier],
                EnhancementId = enhancement[tier],
                ColorCrystalId = colorcrystal[tier],
                AugmentId = augment[tier],

            };
        }
        #endregion

        private string[] _characterDisplayCalculationLabels = null;
        public override string[] CharacterDisplayCalculationLabels
        {
            get
            {
                if (_characterDisplayCalculationLabels == null)
                    _characterDisplayCalculationLabels = new string[] {
                    "General:Health",
                    "General:Mana",
                    "General:Item Level",
//                    "General:Speed",
                    "Spell:Spell Power",
                    "Spell:Haste",
                    "Spell:Hit",
                    "Spell:Penetration",
                    "Spell:Mana Regen",
                    "Spell:Combat Regen",
                    "Spell:Crit Chance",
                    "Spell:Mastery",
                    "Model:Role",
                    "Model:Burst Goal*This is your goal for Burst Healing output.\nYour potential healing done limited by time.\nThis value is Heal Per Second (HPS)",
                    "Model:Sust. Goal*This is your goal for Sustained Healing output.\nThe healing needed over an entire fight adjusted for Damage Evasion and Reduction.\nThis value is Heal Per Second (HPS).",
                    "Model:Mana Goal*This is the Mana you need to fuel your Sustained healing.\nThis value is Total Mana needed over fight.",
                    "Model:Burst*This is your Burst Score. (0-100000)",
                    "Model:Sustained*This is your Sustained Score. (0-100000)",
                    "Model:Mana *This is your Mana Score. (0-100000)",
                    "Holy Spells:Heal",
                    "Holy Spells:Binding Heal",
                    "Holy Spells:Greater Heal",
                    "Holy Spells:Flash Heal",
                    "Holy Spells:Renew",
                    "Holy Spells:ProM*Prayer of Mending",
                    "Holy Spells:ProM 5 Hits*Prayer of Mending hitting 5 targets",
                    "Holy Spells:PWS*Power Word Shield",
                    "Holy Spells:ProH*Prayer of Healing",
                    "Holy Spells:Holy Nova",
                    "Holy Spells:Lightwell",
                    "Holy Spells:CoH*Circle of Healing",
                    "Holy Spells:Penance",
                    "Holy Spells:HW Serenity*Holy Word Serenity",
                    "Holy Spells:HW Sanctuary*Holy Word Sanctuary",
                    "Holy Spells:Gift of the Naaru",
                    "Holy Spells:Divine Hymn",
                    "Holy Spells:Resurrection",
                    "Shadow Spells:Halleluja",
                    "Attributes:Strength",
                    "Attributes:Agility",
                    "Attributes:Stamina",
                    "Attributes:Intellect",
                    "Attributes:Spirit",
                    "Defense:Armor",
                    "Defense:Dodge",
                    "Defense:Resilience",
                    "Resistance:Arcane",
                    "Resistance:Fire",
                    "Resistance:Nature",
                    "Resistance:Frost",
                    "Resistance:Shadow",
                };
                return _characterDisplayCalculationLabels;
            }
        }

        private string[] _optimizableCalculationLabels = null;
        public override string[] OptimizableCalculationLabels
        {
            get
            {
                if (_optimizableCalculationLabels == null)
                    _optimizableCalculationLabels = new string[] {
                    "Health",
                    "Resilience",
                    "Mana",
                    "Mana Regen",
                    "Combat Regen",
                    "Haste Rating",
                    "Mastery Rating",
                    "Haste %",
                    "Renew Ticks",
                    "Crit Rating",
                    //"Spell Crit %",
                    //"PW:Shield",
                    //"GHeal Avg",
                    //"FHeal Avg",
                    //"CoH Avg",
                    "Armor",
                    "Arcane Resistance",
                    "Fire Resistance",
                    "Frost Resistance",
                    "Nature Resistance",
                    "Shadow Resistance",
                    };
                return _optimizableCalculationLabels;
            }
        }

        private ICalculationOptionsPanel _calculationOptionsPanel = null;
        public override ICalculationOptionsPanel CalculationOptionsPanel { get { return _calculationOptionsPanel ?? (_calculationOptionsPanel = new CalculationOptionsPanelHealMerc()); } }

        public override CharacterClass TargetClass { get { return CharacterClass.Mercenary; } }
        public override ComparisonCalculationBase CreateNewComparisonCalculation() { return new ComparisonCalculationHealMerc(); }
        public override CharacterCalculationsBase CreateNewCharacterCalculations() { return new CharacterCalculationsHealMerc(); }

        public override ICalculationOptionBase DeserializeDataObject(string xml)
        {
            System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(CalculationOptionsHealMerc));
            System.IO.StringReader reader = new System.IO.StringReader(xml.Replace("CalculationOptionsPriest", "CalculationOptionsHealMerc").Replace("CalculationOptionsHolyPriest", "CalculationOptionsHealMerc"));
            CalculationOptionsHealMerc calcOpts = serializer.Deserialize(reader) as CalculationOptionsHealMerc;
            return calcOpts;
        }

        #region Relevancy
        public override void SetDefaults(Character character)
        {
            character.ActiveBuffsAdd("Arcane Brilliance (Mana)");
            character.ActiveBuffsAdd("Blessing of Kings");
            character.ActiveBuffsAdd("Blessing of Might (Mp5)");
            character.ActiveBuffsAdd("Devotion Aura");
            character.ActiveBuffsAdd("Flask of the Draconic Mind");
            character.ActiveBuffsAdd("Intellect Food");
            character.ActiveBuffsAdd("Power Word: Fortitude");
            character.ActiveBuffsAdd("Rampage");
            character.ActiveBuffsAdd("Resistance Aura");
            character.ActiveBuffsAdd("Totemic Wrath");
            character.ActiveBuffsAdd("Vampiric Touch");
            character.ActiveBuffsAdd("Wrath of Air Totem");
            character.ActiveBuffsAdd("Mana Tide Totem");
        }

        private static List<string> _relevantGlyphs;
        public override List<string> GetRelevantGlyphs()
        {
            if (_relevantGlyphs == null)
            {
                _relevantGlyphs = new List<string>();
                _relevantGlyphs.Add("Glyph of Circle of Healing");
                _relevantGlyphs.Add("Glyph of Flash Heal");
                _relevantGlyphs.Add("Glyph of Guardian Spirit");
                _relevantGlyphs.Add("Glyph of Holy Nova");
                _relevantGlyphs.Add("Glyph of Hymn of Hope");
                _relevantGlyphs.Add("Glyph of Inner Fire");
                _relevantGlyphs.Add("Glyph of Lightwell");
                _relevantGlyphs.Add("Glyph of Mass Dispel");
                _relevantGlyphs.Add("Glyph of Penance");
                _relevantGlyphs.Add("Glyph of Power Word: Shield");
                _relevantGlyphs.Add("Glyph of Prayer of Healing");
                _relevantGlyphs.Add("Glyph of Renew");
                _relevantGlyphs.Add("Glyph of Fading");
                _relevantGlyphs.Add("Glyph of Power Word: Barrier");
                _relevantGlyphs.Add("Glyph of Prayer of Mending");
                _relevantGlyphs.Add("Glyph of Divine Accuracy");
                _relevantGlyphs.Add("Glyph of Smite");
                _relevantGlyphs.Add("Glyph of Shadowfiend");
                _relevantGlyphs.Add("Glyph of Fortitude");

            }
            return _relevantGlyphs;
        }

        private List<ItemType> _relevantItemTypes = null;
        public override List<ItemType> RelevantItemTypes
        {
            get {
                if (_relevantItemTypes == null) {
                    _relevantItemTypes = new List<ItemType>(new ItemType[]{
                        ItemType.None,
                        ItemType.Light,
                        ItemType.Vibroknife,
                        ItemType.BlasterPistol,
                        ItemType.Lightsaber,
                        ItemType.TechStaff
                    });
                }
                return _relevantItemTypes;
            }
        }

        public override bool ItemFitsInSlot(Item item, Character character, CharacterSlot slot, bool ignoreUnique)
        {
            if (slot == CharacterSlot.OffHand && item.Slot == ItemSlot.OneHand) return false;
            return base.ItemFitsInSlot(item, character, slot, ignoreUnique);
        }

        public override Stats GetRelevantStats(Stats stats)
        {
            Stats s = new Stats()
            {
                Endurance = stats.Endurance,
                Willpower = stats.Willpower,
                Aim = stats.Aim,
                Health = stats.Health,
                Force = stats.Force,
                Fp5 = stats.Fp5,
                Power = stats.Power,

                Alacrity = stats.Alacrity,
                //SpellCrit = stats.SpellCrit,

                CritRating = stats.CritRating,
                AlacrityRating = stats.AlacrityRating,

                BonusWillpowerMultiplier = stats.BonusWillpowerMultiplier,
                BonusAimMultiplier = stats.BonusAimMultiplier,
                BonusForceMultiplier = stats.BonusForceMultiplier,
                BonusCritHealMultiplier = stats.BonusCritHealMultiplier,

                //SpellDamageFromSpiritPercentage = stats.SpellDamageFromSpiritPercentage,
                HealingReceivedMultiplier = stats.HealingReceivedMultiplier,
                BonusHealingDoneMultiplier = stats.BonusHealingDoneMultiplier,
                BonusHealthMultiplier = stats.BonusHealthMultiplier,
                ForceRestoreFromMaxForcePerSecond = stats.ForceRestoreFromMaxForcePerSecond,
                Healed = stats.Healed,
                HealedPerSP = stats.HealedPerSP,

                ForceRestore = stats.ForceRestore,
                SpellsForceCostReduction = stats.SpellsForceCostReduction,

                Armor = stats.Armor,
                Cunning = stats.Cunning,
                Strength = stats.Strength,
                KineticResistance = stats.KineticResistance,
                KineticResistanceBuff = stats.KineticResistanceBuff,
                EnergyResistance = stats.EnergyResistance,
                EnergyResistanceBuff = stats.EnergyResistanceBuff,
                InternalResistance = stats.InternalResistance,
                InternalResistanceBuff = stats.InternalResistanceBuff,
                ElementalResistance = stats.ElementalResistance,
                ElementalResistanceBuff = stats.ElementalResistanceBuff,

                SnareRootDurReduc = stats.SnareRootDurReduc,
                FearDurReduc = stats.FearDurReduc,
                StunDurReduc = stats.StunDurReduc,
                MovementSpeed = stats.MovementSpeed,
            };

            foreach (SpecialEffect se in stats.SpecialEffects())
                if (RelevantTrinket(se))
                    s.AddSpecialEffect(se);
            return s;
        }

        protected bool RelevantTrinket(SpecialEffect se)
        {
            if (se.Trigger == Trigger.HealingSpellCast
                || se.Trigger == Trigger.HealingSpellCrit
                || se.Trigger == Trigger.HealingSpellHit
                || se.Trigger == Trigger.SpellCast
                || se.Trigger == Trigger.SpellCrit
                || se.Trigger == Trigger.DamageOrHealingDone
                || se.Trigger == Trigger.Use)
            {
                return _HasRelevantStats(se.Stats) || (se.Stats._rawSpecialEffectDataSize > 0 && _HasRelevantStats(se.Stats._rawSpecialEffectData[0].Stats));
            }
            return false;
        }

        protected bool _HasRelevantStats(Stats stats)
        {
            bool Yes = (
                stats.Willpower + stats.Aim + stats.Force + stats.Fp5 + stats.Power
                + stats.Alacrity + /*stats.SpellCrit +*/ stats.AlacrityRating + stats.CritRating
                + stats.BonusWillpowerMultiplier + stats.BonusAimMultiplier + stats.BonusForceMultiplier + stats.BonusCritHealMultiplier
                + stats.HealingReceivedMultiplier + stats.BonusHealingDoneMultiplier
                + stats.ForceRestoreFromMaxForcePerSecond + stats.Healed + stats.HealedPerSP

                + stats.ForceRestore + stats.SpellsForceCostReduction
            ) != 0;

            bool Maybe = (
                stats.Endurance + stats.Health
                + stats.Armor + stats.Cunning +
                /*+ stats.SpellHit*/ + stats.AccuracyRating
                + stats.KineticResistance + stats.KineticResistanceBuff
                + stats.EnergyResistance + stats.EnergyResistanceBuff
                + stats.InternalResistance + stats.InternalResistanceBuff
                + stats.ElementalResistance + stats.ElementalResistanceBuff
                + stats.SnareRootDurReduc + stats.FearDurReduc + stats.StunDurReduc + stats.MovementSpeed
            ) != 0;

            bool No = (
                stats.Strength + stats.Power
                + stats.ArmorPenetration + stats.TargetArmorReduction
                + stats.ExpertiseRating
                + stats.Defense + stats.DefenseRating
                + stats.Dodge
                + stats.Dodge
                + stats.Parry
                //+ stats.PhysicalHit
            ) != 0;

            return Yes || (Maybe && !No);
        }

        public override bool HasRelevantStats(Stats stats)
        {
            bool isRelevant = _HasRelevantStats(stats);

            foreach (SpecialEffect se in stats.SpecialEffects())
                isRelevant |= RelevantTrinket(se);
            return isRelevant;
        }

        public Stats GetBuffsStats(Character character, CalculationOptionsHealMerc calcOpts) {
            List<Buff> removedBuffs = new List<Buff>();
            List<Buff> addedBuffs = new List<Buff>();

            //float hasRelevantBuff;

            #region Passive Ability Auto-Fixing
            // Removes the Trueshot Aura Buff and it's equivalents Unleashed Rage and Abomination's Might if you are
            // maintaining it yourself. We are now calculating this internally for better accuracy and to provide
            // value to relevant talents
            /*{
                hasRelevantBuff = character.HunterTalents.TrueshotAura;
                Buff a = Buff.GetBuffByName("Trueshot Aura");
                Buff b = Buff.GetBuffByName("Unleashed Rage");
                Buff c = Buff.GetBuffByName("Abomination's Might");
                if (hasRelevantBuff > 0)
                {
                    if (character.ActiveBuffs.Contains(a)) { character.ActiveBuffs.Remove(a); removedBuffs.Add(a); }
                    if (character.ActiveBuffs.Contains(b)) { character.ActiveBuffs.Remove(b); removedBuffs.Add(b); }
                    if (character.ActiveBuffs.Contains(c)) { character.ActiveBuffs.Remove(c); removedBuffs.Add(c); }
                }
            }
            // Removes the Hunter's Mark Buff and it's Children 'Glyphed', 'Improved' and 'Both' if you are
            // maintaining it yourself. We are now calculating this internally for better accuracy and to provide
            // value to relevant talents
            {
                hasRelevantBuff =  character.HunterTalents.ImprovedHuntersMark
                                + (character.HunterTalents.GlyphOfHuntersMark ? 1 : 0);
                Buff a = Buff.GetBuffByName("Hunter's Mark");
                Buff b = Buff.GetBuffByName("Glyphed Hunter's Mark");
                Buff c = Buff.GetBuffByName("Improved Hunter's Mark");
                Buff d = Buff.GetBuffByName("Improved and Glyphed Hunter's Mark");
                // Since we are doing base Hunter's mark ourselves, we still don't want to double-dip
                if (character.ActiveBuffs.Contains(a)) { character.ActiveBuffs.Remove(a); /*removedBuffs.Add(a);*//* }
                // If we have an enhanced Hunter's Mark, kill the Buff
                if (hasRelevantBuff > 0) {
                    if (character.ActiveBuffs.Contains(b)) { character.ActiveBuffs.Remove(b); /*removedBuffs.Add(b);*//* }
                    if (character.ActiveBuffs.Contains(c)) { character.ActiveBuffs.Remove(c); /*removedBuffs.Add(c);*//* }
                    if (character.ActiveBuffs.Contains(d)) { character.ActiveBuffs.Remove(d); /*removedBuffs.Add(c);*//* }
                }
            }*/
            #endregion

            Stats statsBuffs = GetBuffsStats(character.ActiveBuffs, character.SetBonusCount);

            foreach (Buff b in removedBuffs) {
                character.ActiveBuffsAdd(b);
            }
            foreach (Buff b in addedBuffs) {
                character.ActiveBuffs.Remove(b);
            }

            return statsBuffs;
        }

        #endregion

        #region Custom Charts

        private string _currentChartName = null;
        private float _currentChartTotal = 0;

        private string[] _customChartNames = null;
        private const string _customChartManaSources = "Mana Regen Sources";
        private const string _customChartStatsGraph = "Stats Graph";
        public override string[] CustomChartNames
        {
            get
            {
                if (_customChartNames == null)
                    _customChartNames = new string[] { _customChartManaSources, _customChartStatsGraph };
                return _customChartNames;
            }
        }

        public override ComparisonCalculationBase[] GetCustomChartData(Character character, string chartName)
        {
            List<ComparisonCalculationBase> comparisonList = new List<ComparisonCalculationBase>();
            ComparisonCalculationBase comparison;
            CalculationOptionsHealMerc calcOpts = character.CalculationOptions as CalculationOptionsHealMerc;
            if (calcOpts == null)
                return null;
            CharacterCalculationsHealMerc calcs = GetCharacterCalculations(character) as CharacterCalculationsHealMerc;
            if (calcs == null)
                return null;

            _currentChartTotal = 0;
            _currentChartName = chartName;
            switch (chartName)
            {
                case _customChartManaSources:
                    PriestSolver solver = PriestModels.GetModel(calcs, calcOpts, true);
                    solver.Solve();
                    
                    foreach (ManaSource manaSource in solver.ManaSources)
                    {
                        comparison = CreateNewComparisonCalculation();
                        comparison.Name = manaSource.Name;
                        comparison.Description = manaSource.Description;
                        comparison.SubPoints[2] = manaSource.Value * 5f; // Convert to Mp5
                        _currentChartTotal += comparison.SubPoints[2];
                        comparison.OverallPoints = comparison.SubPoints[2];
                        comparison.Equipped = false;
                        comparisonList.Add(comparison);
                    }
                    return comparisonList.ToArray();
                //case _customChartStatsGraph:
                //    return new ComparisonCalculationBase[0];
                #region old old old
                /*case "Spell AoE HpS":
                    _currentChartName = chartName;
                    p = GetCharacterCalculations(character) as CharacterCalculationsHealMerc;
                    spellList = new List<Spell>();
                    spellList.Add(new Renew(p.BasicStats, character));
                    spellList.Add(new FlashHeal(p.BasicStats, character));
                    spellList.Add(new Heal(p.BasicStats, character));
                    spellList.Add(new PrayerOfHealing(p.BasicStats, character, 5));
                    spellList.Add(new BindingHeal(p.BasicStats, character));
                    spellList.Add(new PrayerOfMending(p.BasicStats, character, 5));
                    spellList.Add(new CircleOfHealing(p.BasicStats, character, 5));
                    spellList.Add(new HolyNova(p.BasicStats, character, 5));
                    spellList.Add(new Penance(p.BasicStats, character));
                    spellList.Add(new PowerWordShield(p.BasicStats, character));

                    foreach (Spell spell in spellList)
                    {
                        if(spell.AvgHeal == 0)
                            continue;

                        comparison = CreateNewComparisonCalculation();
                        comparison.Name = spell.Name;
                        comparison.Equipped = false;
                        comparison.SubPoints[0] = spell.HpS;
                        comparison.OverallPoints = comparison.SubPoints[0];
                        comparisonList.Add(comparison);
                    }

                    return comparisonList.ToArray();
                case "Spell AoE HpM":
                    _currentChartName = chartName;
                    p = GetCharacterCalculations(character) as CharacterCalculationsHealMerc;
                    spellList = new List<Spell>();
                    spellList.Add(new Renew(p.BasicStats, character));
                    spellList.Add(new FlashHeal(p.BasicStats, character));
                    spellList.Add(new Heal(p.BasicStats, character));
                    spellList.Add(new PrayerOfHealing(p.BasicStats, character, 5));
                    spellList.Add(new BindingHeal(p.BasicStats, character));
                    spellList.Add(new PrayerOfMending(p.BasicStats, character, 5));
                    spellList.Add(new CircleOfHealing(p.BasicStats, character, 5));
                    spellList.Add(new HolyNova(p.BasicStats, character, 5));
                    spellList.Add(new Penance(p.BasicStats, character));
                    spellList.Add(new PowerWordShield(p.BasicStats, character));

                    foreach (Spell spell in spellList)
                    {
                        if (spell.AvgHeal == 0)
                            continue;

                        comparison = CreateNewComparisonCalculation();
                        comparison.Name = spell.Name;
                        comparison.Equipped = false;
                        comparison.SubPoints[0] = spell.HpM;
                        comparison.OverallPoints = comparison.SubPoints[0];
                        comparisonList.Add(comparison);
                    }

                    return comparisonList.ToArray();
                case "Spell HpS":
                    _currentChartName = chartName;
                    p = GetCharacterCalculations(character) as CharacterCalculationsHealMerc;
                    spellList = new List<Spell>();
                    spellList.Add(new Renew(p.BasicStats, character));
                    spellList.Add(new FlashHeal(p.BasicStats, character));
                    spellList.Add(new Heal(p.BasicStats, character));
                    spellList.Add(new PrayerOfHealing(p.BasicStats, character, 1));
                    spellList.Add(new BindingHeal(p.BasicStats, character));
                    spellList.Add(new PrayerOfMending(p.BasicStats, character, 1));
                    spellList.Add(new CircleOfHealing(p.BasicStats, character, 1));
                    spellList.Add(new HolyNova(p.BasicStats, character, 1));
                    spellList.Add(new Penance(p.BasicStats, character));
                    spellList.Add(new PowerWordShield(p.BasicStats, character));

                    foreach (Spell spell in spellList)
                    {
                        if (spell.AvgHeal == 0)
                            continue;

                        comparison = CreateNewComparisonCalculation();
                        comparison.Name = spell.Name;
                        comparison.Equipped = false;
                        comparison.SubPoints[0] = spell.HpS;
                        comparison.OverallPoints = comparison.SubPoints[0];
                        comparisonList.Add(comparison);
                    }

                    return comparisonList.ToArray();
                case "Spell HpM":
                    _currentChartName = chartName;
                    p = GetCharacterCalculations(character) as CharacterCalculationsHealMerc;
                    spellList = new List<Spell>();
                    spellList.Add(new Renew(p.BasicStats, character));
                    spellList.Add(new FlashHeal(p.BasicStats, character));
                    spellList.Add(new Heal(p.BasicStats, character));
                    spellList.Add(new PrayerOfHealing(p.BasicStats, character, 1));
                    spellList.Add(new BindingHeal(p.BasicStats, character));
                    spellList.Add(new PrayerOfMending(p.BasicStats, character, 1));
                    spellList.Add(new CircleOfHealing(p.BasicStats, character, 1));
                    spellList.Add(new HolyNova(p.BasicStats, character, 1));
                    spellList.Add(new Penance(p.BasicStats, character));
                    spellList.Add(new PowerWordShield(p.BasicStats, character));

                    foreach (Spell spell in spellList)
                    {
                        if (spell.AvgHeal == 0)
                            continue;

                        comparison = CreateNewComparisonCalculation();
                        comparison.Name = spell.Name;
                        comparison.Equipped = false;
                        comparison.SubPoints[0] = spell.HpM;
                        comparison.OverallPoints = comparison.SubPoints[0];
                        comparisonList.Add(comparison);
                    }

                    return comparisonList.ToArray();
                    */
                #endregion
                default:
                    return new ComparisonCalculationBase[0];
            }
        }

        public override System.Windows.Controls.Control GetCustomChartControl(string chartName)
        {
            switch (chartName)
            {
                case _customChartStatsGraph:
                    return Graph.Instance;
                default:
                    return null;
            }
        }

        public override void UpdateCustomChartData(Character character, string chartName, System.Windows.Controls.Control control)
        {
            switch (chartName)
            {
                case _customChartStatsGraph:
                    Color[] statColors = new Color[] {
                        Color.FromArgb(0xFF, 0xFF, 0x00, 0x00), 
                        Color.FromArgb(0xFF, 0x00, 0x00, 0xFF), 
                        Color.FromArgb(0xFF, 0xFF, 0xFF, 0x00), 
                        Color.FromArgb(0xFF, 0x00, 0x00, 0x00), 
                        Color.FromArgb(0xFF, 0xFF, 0xCC, 0x00), 
                        Color.FromArgb(0xFF, 0x00, 0xFF, 0x00), 
                        Color.FromArgb(0xFF, 0x00, 0xCC, 0xFF),
                    };

                    List<float> X = new List<float>();
                    List<ComparisonCalculationBase[]> Y = new List<ComparisonCalculationBase[]>();

                    Stats[] statsList = new Stats[] {
                                new Stats() { Willpower = 10 },
                                new Stats() { Aim = 10 },
                                new Stats() { AlacrityRating = 10 },
                                new Stats() { CritRating = 10 },
                                new Stats() { Fp5 = 10 },
                            };

                    Graph.Instance.UpdateStatsGraph(character, statsList, statColors, 500, "", null);
                    break;
            }
        }

        private Dictionary<string, Color> _subPointNameColors = null;
        public override Dictionary<string, Color> SubPointNameColors
        {
            get
            {
                if (_subPointNameColors == null)
                {
                    _subPointNameColors = new Dictionary<string, Color>();
                    _subPointNameColors.Add("Burst", Color.FromArgb(255, 192, 0, 0));
                    _subPointNameColors.Add("Sustained", Color.FromArgb(255, 192, 96, 96));
                    _subPointNameColors.Add("Mana", Color.FromArgb(255, 0, 0, 192));
                }
                return _subPointNameColors;
                /*
                switch (_currentChartName)
                {
                    case _customChartManaSources:
                        _subPointNameColors = new Dictionary<string, Color>();
                        _subPointNameColors.Add("Mana", Color.FromArgb(255, 0, 0, 192));
                        break;
                    case _customChartStatsGraph:
                        _subPointNameColors = new Dictionary<string, Color>();
                        break;
                    default:
                        _subPointNameColors = new Dictionary<string, Color>();
                        _subPointNameColors.Add("Burst", Color.FromArgb(255, 192, 0, 0));
                        _subPointNameColors.Add("Sustained", Color.FromArgb(255, 192, 96, 96));
                        _subPointNameColors.Add("Mana", Color.FromArgb(255, 0, 0, 192));
                        break;
                }
                return _subPointNameColors;*/
            }
        }

        #endregion

        public override CharacterCalculationsBase GetCharacterCalculations(Character character, Item additionalItem, bool referenceCalculation, bool significantChange, bool needsDisplayCalculations)
        {
            // First things first, we need to ensure that we aren't using bad data
            CharacterCalculationsHealMerc calc = new CharacterCalculationsHealMerc();
            if (character == null) { return calc; }
            CalculationOptionsHealMerc calcOpts = character.CalculationOptions as CalculationOptionsHealMerc;
            if (calcOpts == null) { return calc; }

            calc.BasicStats = GetCharacterStats(character, additionalItem) as StatsPriest;
            calc.Character = character;

            PriestSolver solver = PriestModels.GetModel(calc, calcOpts, needsDisplayCalculations);
            solver.Solve();
            
            return calc;
        }

        public override Stats GetCharacterStats(Character character, Item additionalItem)
        {           
            CalculationOptionsHealMerc calcOpts = character.CalculationOptions as CalculationOptionsHealMerc;

            StatsPriest statsTotal = new StatsPriest()
            {
                Alacrity = PriestInformation.GetDarkness(0/*character.MercenaryTalents.Darkness*/),
                InnerFire = true,
                BonusWillpowerMultiplier = 0.05f,   // Cloth bonus.
                PriestSpec = PriestSpec.GetPriestSpec(character.MercenaryTalents),
            };
            if (statsTotal.PriestSpec == ePriestSpec.Spec_Disc)
            {
                statsTotal.SpellCombatForceRegeneration = 0.5f;
                statsTotal.BonusWillpowerMultiplier = 0.15f;
            }
            else if (statsTotal.PriestSpec == ePriestSpec.Spec_Holy)
            {
                statsTotal.SpellCombatForceRegeneration = 0.5f + PriestInformation.GetHolyConcentration(0/*character.MercenaryTalents.HolyConcentration*/);
                statsTotal.BonusHealingDoneMultiplier = 0.15f;
            }
            else if (statsTotal.PriestSpec == ePriestSpec.Spec_ERROR)
            {
                throw new Exception("Unpossible Talent Spec!");
            }

            statsTotal.Accumulate(BaseStats.GetBaseStats(character));
            statsTotal.Accumulate(GetItemStats(character, additionalItem));
            statsTotal.Accumulate(GetBuffsStats(character, calcOpts));

          
            statsTotal.Endurance = (float)Math.Floor((statsTotal.Endurance) * (1 + statsTotal.BonusEnduranceMultiplier));
            statsTotal.Willpower = (float)Math.Floor((statsTotal.Willpower) * (1 + statsTotal.BonusWillpowerMultiplier));
            statsTotal.Aim = (float)Math.Floor((statsTotal.Aim) * (1 + statsTotal.BonusAimMultiplier));
            statsTotal.Power += (statsTotal.InnerFire ? PriestInformation.GetInnerFireSpellPowerBonus(character) : 0) + (statsTotal.Willpower - 10);
            statsTotal.Power *= (1f + statsTotal.BonusPowerMultiplier);
            statsTotal.Force *= (1f + statsTotal.BonusForceMultiplier);
            statsTotal.Health += StatConversion.GetHealthFromEndurance(statsTotal.Endurance);
            statsTotal.Health = (float)Math.Floor(statsTotal.Health * (1f + statsTotal.BonusHealthMultiplier));
            //statsTotal.SpellCrit += statsTotal.Willpower + StatConversion.GetCritFromRating(statsTotal.CritRating);
            statsTotal.Alacrity = (1f + statsTotal.Alacrity) * (1f + (1f - StatConversion.GetAlacrityModifierFromRating(statsTotal.AlacrityRating))) - 1f;
            statsTotal.Armor *= (1 + (statsTotal.InnerFire ? PriestInformation.GetInnerFireArmorBonus(character) : 0));

            if (statsTotal.PriestSpec == ePriestSpec.Spec_Disc)
            {
                statsTotal.ShieldDiscipline = (PriestInformation.DisciplineMasteryBase) * PriestInformation.DisciplineMasteryEffect;
            }
            else if (statsTotal.PriestSpec == ePriestSpec.Spec_Holy)
            {
                statsTotal.EchoofLight = (PriestInformation.HolyMasteryBase) * PriestInformation.HolyMasteryEffect;
            }

            return statsTotal;
        }

    }
}
